package timing.ukulele.user.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import timing.ukulele.http.OkHttpManager;
import timing.ukulele.user.config.properties.AppProperties;
import timing.ukulele.user.config.properties.MpProperties;
import timing.ukulele.user.model.WxAccessTokenResponse;

import java.io.IOException;
import java.util.Objects;

/**
 * 微信工具类
 */
@Component
@Import({AppProperties.class, MpProperties.class})
public class WeixinMessageUtil {

    private final String wxAppid;
    private final String wxSecret;
//    private final String miniprogramState;

    private final String mpAppid;
    private final String mpAppSecret;


    //消息发送地址
//    private final String messageUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=%s";
    //统一服务消息发送地址
    private final String uniformMessageUrl = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=%s";
    //获取accessToken地址
    private final String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    // 获取用户的unionId
    private final String openInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN";

    private final String MP_MESSAGE_TEMPLATE = "{\"touser\":\"%s\",\"mp_template_msg\":{\"appid\":\"%s\",\"template_id\":\"%s\",\"url\":\"%s\",\"miniprogram\":{\"appid\":\"%s\",\"pagepath\":\"%s\"},\"data\":%s}}";

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");

    private WxAccessTokenResponse accessTokenResponse;
    private WxAccessTokenResponse mpAccessTokenResponse;

    public WeixinMessageUtil(AppProperties appProperties, MpProperties mpProperties) {
        wxAppid = appProperties.getAppid();
        wxSecret = appProperties.getAppsecret();
//        miniprogramState = appProperties.getMiniprogramState();
        mpAppid = mpProperties.getAppid();
        mpAppSecret = mpProperties.getAppsecret();
    }

    /**
     * 向用户发送小程序注册卡片
     *
     * @param toUser 用户openId
     */
    public void sendMpAppCardMessage(String toUser) {
        //发送小程序卡片
        JSONObject subscribeInfoJson = new JSONObject();
        subscribeInfoJson.put("touser", toUser);
        subscribeInfoJson.put("msgtype", "miniprogrampage");
        JSONObject miniprogrampage = new JSONObject();
        miniprogrampage.put("title", "易供云");
        miniprogrampage.put("appid", wxAppid);
        miniprogrampage.put("pagepath", "/pages/navigator/user/index");
        miniprogrampage.put("thumb_media_id", "GNoMruzBspTDSVFES_Nlqx0Wp6WcYt25MuRrBYN8FF_zMYg77xnZeRdF-qmnZWfU");
        subscribeInfoJson.put("miniprogrampage", miniprogrampage);
        String accessToken = getMpAccessToken();
        if (accessToken == null)
            return;
        String url = String.format("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s", accessToken);
        RequestBody body = RequestBody.create(MEDIA_TYPE, subscribeInfoJson.toJSONString());
        Request request = new Request.Builder()
                .url(url).post(body)
                .build();
        try {
            OkHttpManager.INSTANCE.build(null).getClient().newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送公众号消息
     *
     * @param templateId 公众号消息模板id
     * @param openId     公众号openId 如oz46J6P7kvTQEuhBzFD005UAieAA
     * @param page       小程序跳转页面
     * @param content    消息内容
     */
    public void sendMpMessage(String templateId, String openId, String page, String content) {
        String accessToken = getAccessToken();
        if (accessToken == null)
            return;
        String url = String.format(uniformMessageUrl, accessToken);
        String messageBody = String.format(MP_MESSAGE_TEMPLATE, openId, mpAppid, templateId, "https://www.yigongyun.cloud/", wxAppid, page, content);
        RequestBody body = RequestBody.create(MEDIA_TYPE, messageBody);
        Request request = new Request.Builder()
                .url(url).post(body)
                .build();
        try {
            OkHttpManager.INSTANCE.build(null).getClient().newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取accesstoken
     *
     * @return
     */
    public synchronized String getAccessToken() {
        if (accessTokenResponse != null && System.currentTimeMillis() < accessTokenResponse.getExpires_at()) {
            return accessTokenResponse.getAccess_token();
        }
        String url = String.format(accessTokenUrl, wxAppid, wxSecret);
        Request request = new Request.Builder()
                .url(url).get()
                .build();
        try {
            Response response = OkHttpManager.INSTANCE.build(null).getClient().newCall(request).execute();
            if (response.isSuccessful()) {
                try {
                    String responseBody = Objects.requireNonNull(response.body()).string();
                    WxAccessTokenResponse model = JSON.parseObject(responseBody, new TypeReference<WxAccessTokenResponse>() {
                    });
                    if (model != null && (model.getErrcode() == null || model.getErrcode() == 0)) {
                        model.setExpires_at(System.currentTimeMillis() + (model.getExpires_in() - 30) * 1000);
                        accessTokenResponse = model;
                        return model.getAccess_token();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public synchronized String getMpAccessToken() {
        if (mpAccessTokenResponse != null && System.currentTimeMillis() < mpAccessTokenResponse.getExpires_at()) {
            return mpAccessTokenResponse.getAccess_token();
        }
        String url = String.format(accessTokenUrl, mpAppid, mpAppSecret);
        Request request = new Request.Builder()
                .url(url).get()
                .build();
        try {
            Response response = OkHttpManager.INSTANCE.build(null).getClient().newCall(request).execute();
            if (response.isSuccessful()) {
                try {
                    String responseBody = Objects.requireNonNull(response.body()).string();
                    WxAccessTokenResponse model = JSON.parseObject(responseBody, new TypeReference<WxAccessTokenResponse>() {
                    });
                    if (model != null && (model.getErrcode() == null || model.getErrcode() == 0)) {
                        model.setExpires_at(System.currentTimeMillis() + (model.getExpires_in() - 30) * 1000);
                        mpAccessTokenResponse = model;
                        return model.getAccess_token();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getUnionId(String openId) {
        String accessToken = getMpAccessToken();
        if (accessToken == null)
            return null;
        String url = String.format(openInfoUrl, accessToken, openId);
        Request request = new Request.Builder()
                .url(url).get()
                .build();
        try {
            Response response = OkHttpManager.INSTANCE.build(null).getClient().newCall(request).execute();
            if (response.isSuccessful()) {
                String responseBody = Objects.requireNonNull(response.body()).string();
                JSONObject userDetail = JSON.parseObject(responseBody);
                String unionId = userDetail.getString("unionid");
                return unionId;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
